#include "StdAfx.h"
#include "MembersDb.h"

const TCHAR *CMembersDb::DB_NAME = _T("Members");

CMembersDb::CMembersDb(void)
    : CDbBase(DB_NAME, sizeof(Record))
    , m_MaxId(0)
{
}

CMembersDb::~CMembersDb(void)
{
}

DWORD CMembersDb::Open(void)
{
    DWORD Err = CDbBase::Open();
    if (Err != ERROR_SUCCESS)
        return Err;

    UINT Count = GetCount();
    if (Count == UINT_MAX)
        return ERROR_GEN_FAILURE;

    Record r = {0};
    Err = m_DbMgr.ReadRecord(Count - 1, (BYTE *)&r, sizeof(Record), NULL);
    if (Err == ERROR_SUCCESS)
        m_MaxId = r.Id;     // Read can fail if empty

    return ERROR_SUCCESS;
}

DWORD
CMembersDb::Add(
    UINT GroupId,
    CEOID ContactId,
    PROPID ContactNumberPropId,
    UINT *pAssignedId)
{
    Record r = {0};
    r.GroupId = GroupId;
    r.ContactId = ContactId;
    r.ContactNumberPropId = ContactNumberPropId;
    r.Id = m_MaxId + 1;

    UINT Count = GetCount();
    if (Count == UINT_MAX)
        return ERROR_GEN_FAILURE;

    DWORD Err = m_DbMgr.WriteRecord(Count, (BYTE *)&r, sizeof(Record));
    if (Err != ERROR_SUCCESS)
        return Err;

    m_MaxId++;

    if (pAssignedId)
        *pAssignedId = r.Id;

    return ERROR_SUCCESS;
}

DWORD
CMembersDb::Get(
    UINT Index,
    UINT *pId,
    UINT *pGroupId,
    CEOID *pContactId,
    PROPID *pContactNumberPropId)
{
    Record r = {0};
    DWORD Err = m_DbMgr.ReadRecord(Index, (BYTE *)&r, sizeof(Record), NULL);
    if (Err != ERROR_SUCCESS)
        return Err;

    if (pId)
        *pId = r.Id;
    if (pGroupId)
        *pGroupId = r.GroupId;
    if (pContactId)
        *pContactId = r.ContactId;
    if (pContactNumberPropId)
        *pContactNumberPropId = r.ContactNumberPropId;

    return ERROR_SUCCESS;
}

DWORD
CMembersDb::Set(
    UINT Index,
    CEOID ContactId,
    CEPROPID ContactNumberPropId)
{
    UINT Id = 0;
    UINT GroupId = 0;
    DWORD Err = Get(Index, &Id, &GroupId, NULL, NULL);     // Will do all sanity for us
    if (Err != ERROR_SUCCESS)
        return Err;

    Record r = {0};
    r.Id = Id;
    r.GroupId = GroupId;
    r.ContactId = ContactId;
    r.ContactNumberPropId = ContactNumberPropId;

    return m_DbMgr.WriteRecord(Index, (BYTE *)&r, sizeof(Record));
}

DWORD CMembersDb::DeleteByGroupId(UINT GroupId)
{
    UINT Index = 0;
    UINT DbGroupId = 0;
    DWORD Err = Get(Index, NULL, &DbGroupId, NULL, NULL);
    while (Err == ERROR_SUCCESS)
    {
        Index++;

        if (DbGroupId == GroupId)
        {
            Err = Delete(Index);
            if (Err == ERROR_SUCCESS)
                Index--;
        }

        Err = Get(Index, NULL, &DbGroupId, NULL, NULL);
    }

    return ERROR_SUCCESS;
}

DWORD
CMembersDb::GetFromId(
    UINT Id,
    UINT *pGroupId,
    CEOID *pContactId,
    PROPID *pNumberPropId,
    UINT *pIndex)
{
    UINT i = 0;
    Record r = {0};
    DWORD Err = m_DbMgr.ReadRecord(i, (BYTE *)&r, sizeof(Record), NULL);
    while (Err == ERROR_SUCCESS)
    {
        if (Id == r.Id)
        {
            if (pGroupId)
                *pGroupId = r.GroupId;
            if (pContactId)
                *pContactId = r.ContactId;
            if (pNumberPropId)
                *pNumberPropId = r.ContactNumberPropId;
            if (pIndex)
                *pIndex = i;

            return ERROR_SUCCESS;
        }

        i++;
        Err = m_DbMgr.ReadRecord(i, (BYTE *)&r, sizeof(Record), NULL);
    }

    return ERROR_NOT_FOUND;
}

DWORD CMembersDb::CopyFromId(UINT IdDest, UINT IdSrc)
{
    UINT Count = GetCount();
    for (UINT i = 0; i < Count; i++)
    {
        Record r = {0};
        DWORD Err = m_DbMgr.ReadRecord(i, (BYTE *)&r, sizeof(Record), NULL);
        if (Err == ERROR_SUCCESS)
        {
            if (r.GroupId == IdSrc)
            {
                r.GroupId = IdDest;
                Err = Add(r.GroupId, r.ContactId, r.ContactNumberPropId, NULL);
                if (Err != ERROR_SUCCESS)
                    return Err;
            }
        }
    }

    return ERROR_SUCCESS;
}
